package com.cosina.game.tetri.engine.impl;

import java.util.Observable;

import com.cosina.game.tetri.engine.Box;
import com.cosina.game.tetri.engine.Direction;
import com.cosina.game.tetri.engine.Game;
import com.cosina.game.tetri.engine.Point;
import com.cosina.game.tetri.engine.Shape;
import com.cosina.game.tetri.engine.ShapeFactory;

public class BoxImpl extends Observable implements Box {
	
	
	private Shape currentShape;
	
	private final Point size;
	private int[][] content;
	public BoxImpl(Point size){
		this.size = size;
		content = new int[size.y][size.x];
	}
	
	
	public int[][] getContent(){
		int[][] contentCopy = new int[size.y][size.x];
		for(int y=0; y<size.y; y++) {
			for(int x=0; x<size.x; x++) {
				contentCopy[y][x] = content[y][x];
			}
		}
		Point point = currentShape.getLeftTopLocation();
		for(Point part : currentShape.getContent()){
			contentCopy[point.y + part.y][point.x + part.x] = 2 ;
		}
		return contentCopy;
	}
	
	@Override
	public void fill() {
		currentShape = ShapeFactory.getRandom();
		if(checkGoOn() == false){
			statusOver = true;
		}
	}

	@Override
	public void regListener(Game game) {
	}

	@Override
	public Point getSize() {
		return size;
	}


	@Override
	public void handleKeyEvent(Direction direction) {
		if(direction == Direction.left){
			Point point = currentShape.getLeftTopLocation();
			point.x -= 1;
			if(checkGoOn()==false){
				point.x += 1;
				return;
			}
		}else if(direction == Direction.right){
			Point point = currentShape.getLeftTopLocation();
			point.x += 1;
			if(checkGoOn()==false){
				point.x -= 1;
				return;
			}
		}else if(direction == Direction.up){
			currentShape.doTransfrom();
			if(checkGoOn()==false){
				currentShape.doTransfrom();
				return;
			}
		}else if(direction == Direction.down){
			Point point = currentShape.getLeftTopLocation();
			point.y += 1;
			if(checkGoOn()==false){
				System.err.println();
			}
		}else{
			
		}
		
		handleAfterDoSth();
	}


	@Override
	public void handleTimePassEvent() {
		Point point = currentShape.getLeftTopLocation();
		point.y = point.y + 1;
		handleAfterDoSth();
	}
	
	private  void handleAfterDoSth(){
		if(checkCanGoDown()==false){
			combine();
			fill();
		}
	}
	
	private boolean checkCanGoDown(){
		
		Point point = currentShape.getLeftTopLocation();
		point.y += 1;
		
		boolean result = checkGoOn();
		point.y -= 1;
		return result;
	}
	
	private boolean checkGoOn(){
		Point location = currentShape.getLeftTopLocation();
		for(Point part : currentShape.getContent()){
			if((location.y + part.y)>=size.y || (location.y + part.y) < 0)
				return false;
			if((location.x + part.x)>=size.x || (location.x + part.x) < 0)
				return false;
			if(content[location.y + part.y][location.x+part.x]==1){
				return false;
			}
		}
		return true;
	}
	
	private void combine(){
		Point location = currentShape.getLeftTopLocation();
		for(Point part : currentShape.getContent()){
			content[location.y + part.y][location.x + part.x] = 1 ;
		}
		int[] rowsFullFlag = new int[size.y];
		for(int y=size.y-1; y>=0; y--) {
			int rowSum = 0;
			for(int x=0; x<size.x; x++) {
				rowSum += content[y][x];
			}
			if(rowSum == size.x){
				rowsFullFlag[y] = 1;
			}
		}
		
		int dismissRowCount = 0 ;
		
		for(int y=size.y-1; y>=dismissRowCount; y--) {
			dismissRowCount += rowsFullFlag[y];
			for(int x=0; x<size.x; x++) {
				if(dismissRowCount>0){
					content[y][x] = content[y-dismissRowCount][x];
					content[y-dismissRowCount][x] = 0;
				}
			}
		}
	}

private boolean statusOver = false;
	@Override
	public boolean isOver() {
		// TODO Auto-generated method stub
		return statusOver;
	}
}
